package top.winshu.common.web.upload;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import top.winshu.common.exception.WinshuInternalException;
import top.winshu.common.exception.WinshuParseException;
import top.winshu.common.exception.WinshuServiceException;
import top.winshu.common.util.IdGenerator;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * @author winshu
 * @since 2021/6/4
 **/
public class UploadHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(UploadHelper.class);

    @Value("${winshu.file-base-path}")
    private String fileBasePath;

    @Value("${winshu.file-date-path}")
    private DatePathFormat fileDatePath;

    /**
     * 上传文件
     */
    public UploadResult upload(MultipartFile file, String contextPath, String newFileName, List<String> allowedSuffixes) {
        UploadResult result = createResult(file, trimPath(contextPath), newFileName);
        if (!CollectionUtils.isEmpty(allowedSuffixes) && !allowedSuffixes.contains(result.getSuffix())) {
            result.setMessage("不支持的文件后缀格式");
            return result;
        }

        LOGGER.info("上传文件({} KB)，路径 {}", file.getSize() / 1024, result.getFullPath());
        try {
            File target = new File(result.getFullPath());
            FileUtils.copyInputStreamToFile(file.getInputStream(), target);
            result.setSuccess(true);
        } catch (IOException e) {
            LOGGER.warn("上传文件失败, {}", e.getMessage());
            result.setMessage("上传文件失败");
        }
        return result;
    }

    /**
     * 上传文件，支持设置文件名
     */
    public UploadResult upload(MultipartFile file, String contextPath, String fileName) {
        return upload(file, contextPath, fileName, Collections.emptyList());
    }

    /**
     * 上传文件
     */
    public UploadResult upload(MultipartFile file, String contextPath) {
        return upload(file, contextPath, IdGenerator.newId() + "");
    }

    /**
     * 只支持上传图片
     */
    public UploadResult uploadImage(MultipartFile file, String contextPath) {
        ImageInputStream iis;
        try {
            iis = ImageIO.createImageInputStream(file.getInputStream());
        } catch (IOException e) {
            throw new WinshuParseException("上传失败");
        }

        Iterator<?> iter = ImageIO.getImageReaders(iis);
        if (iter.hasNext()) {
            return upload(file, contextPath, IdGenerator.newId() + "");
        }
        throw new WinshuServiceException("只支持上传图片");
    }

    public static String getFileSuffix(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
    }

    /**
     * 加载文件
     */
    public void loadFile(HttpServletResponse response, String filePath, boolean autoBasePath) {
        if (autoBasePath) {
            loadFile(response, MessageFormat.format("{0}/{1}", fileBasePath, trimPath(filePath)));
        } else {
            loadFile(response, filePath);
        }
    }

    /**
     * 加载文件
     */
    public void loadFile(HttpServletResponse response, String fullPath) {
        File file = FileUtils.getFile(fullPath);
        try {
            if (!file.exists() || !file.isFile()) {
                throw new WinshuInternalException("file not found");
            }
            FileUtils.copyFile(file, response.getOutputStream());
        } catch (IOException e) {
            LOGGER.warn("error for coping file to response");
        }
    }

    private static String trimPath(String path) {
        path = path.replace("\\", "/");
        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        if (path.endsWith("/")) {
            path = path.substring(0, path.length() - 1);
        }
        return path;
    }

    /**
     * 创建上传结果
     */
    private UploadResult createResult(MultipartFile file, String contextPath, String newFileName) {
        if (fileDatePath != DatePathFormat.NONE) {
            contextPath = MessageFormat.format("{0}/{1}", contextPath, fileDatePath.toPath());
        }

        String suffix = getFileSuffix(file.getOriginalFilename());
        String filePath = MessageFormat.format("/{0}/{1}.{2}", contextPath, newFileName, suffix);
        String fullPath = MessageFormat.format("{0}/{1}/{2}.{3}", fileBasePath, contextPath, newFileName, suffix);

        UploadResult info = new UploadResult();
        info.setFileSize(file.getSize() / 1024);
        info.setContextPath("/" + contextPath);
        info.setFileName(newFileName);
        info.setFilePath(filePath);
        info.setFullPath(fullPath);
        info.setSuffix(suffix);

        return info;
    }
}
